R Basic

Introduction

R as a calculator

1 + 100
2^2
7/2
4-1
2*2
3+5*2
(3+5)*2
2e2
2/10000
sin(1)
log(1)
exp(0)
1 == 1
1 >= 1
1 < 1
1 != 2
x <- 10
x
x + x
x - 5
x^2
y <- x + x
y

Vectorization

1:5
2^(1:5)
v <- 1:5
2^v
log10(v)

Environment

ls()
rm(v)
ls()

Package Management

installed.packages()
#install.packages("vegan", dependencies = TRUE) #Already installed
library(vegan)
#remove.packages()

Project Management

  1. Set up management structure (i.e., “data”, “src”, “results”, “doc”)
  2. Discuss avoiding redundancy of files
  3. Make sure to use version control (i.e., Git)

Getting Help

?plot
help(plot)
?"<-"
vignette("FAQ-vegan")
citation("vegan")

To cite package ‘vegan’ in publications use:

  Jari Oksanen, F. Guillaume Blanchet, Michael Friendly, Roeland Kindt, Pierre Legendre, Dan McGlinn, Peter R.
  Minchin, R. B. O'Hara, Gavin L. Simpson, Peter Solymos, M. Henry H. Stevens, Eduard Szoecs and Helene Wagner
  (2020). vegan: Community Ecology Package. R package version 2.5-7. https://CRAN.R-project.org/package=vegan

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {vegan: Community Ecology Package},
    author = {Jari Oksanen and F. Guillaume Blanchet and Michael Friendly and Roeland Kindt and Pierre Legendre and Dan McGlinn and Peter R. Minchin and R. B. O'Hara and Gavin L. Simpson and Peter Solymos and M. Henry H. Stevens and Eduard Szoecs and Helene Wagner},
    year = {2020},
    note = {R package version 2.5-7},
    url = {https://CRAN.R-project.org/package=vegan},
  }

ATTENTION: This citation information has been auto-generated from the package DESCRIPTION file and may need
manual editing, see ‘help("citation")’.

Data and their formats

cats <- data.frame(coat = c("calico", "black", "tabby"),
                   weight = c(2.1,5,3.2),
                   likes_string = c(1,0,1))
write.csv(cats, file = "~/GitHub/biol48006220_Fall2022/practcomp_2022/data/cats.csv")
cats$coat
[1] "calico" "black"  "tabby" 
cats$weight
[1] 2.1 5.0 3.2
cats$weight*10
[1] 21 50 32
log(cats$weight)
[1] 0.7419373 1.6094379 1.1631508
cats <- cbind(cats, logweight)
paste("My cat is ", cats$coat, ", and it weighs ", cats$weight, " kg.", sep = "")
[1] "My cat is calico, and it weighs 2.1 kg." "My cat is black, and it weighs 5 kg."   
[3] "My cat is tabby, and it weighs 3.2 kg." 

Data Types

typeof(cats$coat)
[1] "character"
typeof(cats$weight)
[1] "double"
typeof(cats$likes_string)
[1] "double"
typeof(3.14159)
[1] "double"
typeof(1i)
[1] "complex"
typeof(FALSE)
[1] "logical"
typeof(T)
[1] "logical"
typeof(cats)
[1] "list"
class(cats)
[1] "data.frame"
file.show("./data/cats.csv")
typeof(cats$likes_string)
[1] "logical"
cats$likes_string
[1]  TRUE FALSE  TRUE
c("a", "b")
[1] "a" "b"
ab
[1] "a" "b"
c(ab, "c")
[1] "a" "b" "c"
c(ab, ab)
[1] "a" "b" "a" "b"
1:10
 [1]  1  2  3  4  5  6  7  8  9 10
seq(10)
 [1]  1  2  3  4  5  6  7  8  9 10
head(z, n=3)
[1] 1 2 3
length(z)
[1] 10
class(z)
[1] "integer"
typeof(z)
[1] "integer"
seq(0,100, by=5)
 [1]   0   5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90  95 100

Data Frames

str(cats$coat)
 chr [1:3] "calico" "black" "tabby"
coats
[1] "tabby"         "tortoiseshell" "tortoiseshell" "black"         "tabby"        
str(coats)
 chr [1:5] "tabby" "tortoiseshell" "tortoiseshell" "black" "tabby"
factor(coats)
[1] tabby         tortoiseshell tortoiseshell black         tabby        
Levels: black tabby tortoiseshell
class(categories)
[1] "factor"
str(categories)
 Factor w/ 3 levels "black","tabby",..: 2 3 3 1 2

Lists

list_example <- list(title="Numbers", numbers = 1:10, data=T)
list_example
$title
[1] "Numbers"

$numbers
 [1]  1  2  3  4  5  6  7  8  9 10

$data
[1] TRUE
another_list
[[1]]
[1] 1

[[2]]
[1] "a"

[[3]]
[1] TRUE

[[4]]
[1] 1+1i
class(list_example)
[1] "list"
class(cats)
[1] "data.frame"

Matrices

# By definition, matrices are all numbers

matrix_example <- matrix(0, ncol = 5, nrow = 3)
matrix_example
class(matrix_example)
typeof(matrix_example)
str(matrix_example)
dim(matrix_example)
ncol(matrix_example)
nrow(matrix_example)
class(data.frame(matrix_example))
df_example <- data.frame(matrix_example)
df_example

Subsetting

p <- c(2.3, 6.9, 4.0, 23, 1)
p
names(p) <- c('a', 'b', 'c', 'd', 'e')
p
p[1]
p[2:4]
p[c(1,5)]
p[c(1,1,1,3,5,5)]
p[6]
p[-3]
p[c(-1,-5)]
p[-(2:4)]
p[c('a','c')]
p[c(T,F,T,F,T)]
p[names(p) != 'c']

Factors

f <- factor(c('a','b','c','d','e'))
f
f[f=='a']
f[1:3]
f[f %in% c('b','c')]
f[-3]
f2 <- factor(c('a','a','d','c','c'))
f2
f2[f2 == 'a']
f2[f2 %in% c('a','c')]

Matrices Resumed

m
           [,1]       [,2]       [,3]        [,4]
[1,] -1.1968205 -0.3943568  0.4232027 -2.34367583
[2,] -0.9516674 -1.2484030 -1.8461725 -0.77605977
[3,]  0.2786364 -0.6521289 -0.2456747 -2.16173144
[4,] -1.4449411 -1.1707346  1.2538299  0.05701057
[5,]  0.8216518  0.3604497  1.5633419 -0.24867199
[6,]  1.2470188  1.2302708 -1.2644661 -0.07830796
m[,c(3,4)]
           [,1]        [,2]
[1,]  0.4232027 -2.34367583
[2,] -1.8461725 -0.77605977
[3,] -0.2456747 -2.16173144
[4,]  1.2538299  0.05701057
[5,]  1.5633419 -0.24867199
[6,] -1.2644661 -0.07830796

Lists Revisted

xlist
$a
[1] "BIOL48006220"

$b
 [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0  8.5  9.0  9.5 10.0

$data
[1] "Grade"
xlist[1:2]
$a
[1] "BIOL48006220"

$b
 [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0  8.5  9.0  9.5 10.0
xlist['a']
$a
[1] "BIOL48006220"
xlist[['a']]
[1] "BIOL48006220"
xlist[['b']]
 [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0  8.5  9.0  9.5 10.0
xlist$b
 [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0  8.5  9.0  9.5 10.0

Data Frames Revisted

gp <- read.csv("/Users/colinfinlay/GitHub/biol48006220_Fall2022/practcomp_2022/data/forest_area_sq_km.numbers")
Warning: line 1 appears to contain embedded nullsWarning: line 3 appears to contain embedded nullsWarning: line 4 appears to contain embedded nullsWarning: line 5 appears to contain embedded nullsWarning: EOF within quoted stringWarning: embedded nul(s) found in input
head(gp, n=10L)
Warning messages:
1: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘tibble’ 
2: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘pillar’ 
nrow(gp)
[1] 214
head(gp[["country"]], 10L)
 [1] "Aruba"                "Afghanistan"          "Angola"               "Albania"              "Andorra"             
 [6] "United Arab Emirates" "Argentina"            "Armenia"              "American Samoa"       "Antigua and Barbuda" 
gp$X2001
  [1] "4.2"   "12.1k" "766k"  "7720"  "160"   "3110"  "327k"  "3320"  "177"   "93.2"  "1.31M" "38.4k" "9960"  "1940"  "6720" 
 [16] "40.4k" "71.2k" "19.1k" "34.5k" "4"     "5100"  "21.1k" "83.4k" "14.5k" "10"    "547k"  "5.43M" "63"    "3940"  "26.3k"
 [31] "174k"  "228k"  "3.48M" "8.68"  "12k"   "160k"  "1.82M" "48.7k" "215k"  "1.43M" "222k"  "623k"  "408"   "403"   "28.6k"
 [46] "25.3k" "129"   "1720"  "26.4k" "114k"  "56"    "479"   "5750"  "19.9k" "16.5k" "136k"  "605"   "11.1k" "174k"  "22.6k"
 [61] "184k"  "224k"  "10.2k" "155k"  "0.8"   "639"   "237k"  "34.6"  "29.8k" "27.7k" "86.7k" "0"     "68.6k" "3460"  "21.3k"
 [76] "26k"   "36.6k" "177"   "2.2"   "41.1k" "240"   "186k"  "67.4k" "18.9k" "3800"  "19.5k" "1.01M" "680k"  "6480"  "96k"  
 [91] "8190"  "328"   "1530"  "85k"   "5280"  "975"   "249k"  "31.4k" "38.9k" "11.9k" "107k"  "11.8"  "110"   "64.6k" "51.3" 
[106] "173k"  "1380"  "81.6k" "2170"  "210"   "67"    "21.5k" "345"   "20.5k" "871"   "32.7k" "10"    "55.4k" "0"     "3500" 
[121] "129k"  "8.2"   "681k"  "94"    "9580"  "133k"  "3.5"   "342k"  "6260"  "142k"  "316"   "407k"  "4110"  "412"   "30k"  
[136] "195k"  "79.2k" "8380"  "13k"   "246k"  "51.6k" "3620"  ""      "121k"  "58.2k" "0"     "98.5k" "30"    "44.3k" "44.2k"
[151] "750k"  "72.2k" "398"   "363k"  "91.1k" "4420"  "64.1k" "32.8k" "223k"  "91.2"  "1490"  "0"     "64k"   "8.1M"  "2830" 
[166] "9770"  ""      "87.8k" "172"   "25.4k" "28.9k" "6650"  "10"    "73.6k" "24.8k" ""      "583"   "153k"  "19k"   "12.4k"
[181] "281k"  "4760"  ""      "337"   "4440"  "105"   "61.9k" "12.6k" "192k"  "4100"  "41.3k" "9460"  "89.5"  "2360"  "6720" 
[196] "203k"  "10"    "529k"  "30.8k" "95.2k" "14.4k" "3.05M" "30.4k" "285"   "488k"  "36.6"  "201"   "121k"  "4420"  "1700" 
[211] "5490"  "177k"  "470k"  "183k" 

Conditionals and Flow

if (n<10) {
  print("n is less than 10")
} else if (n>10) {
  print("n is greater than 10")
} else {
  print("n is equal to 10")
}
[1] "n is equal to 10"
for (n in seq(1,20)) {
  if (n<10) {
    print("n is less than 10")
  } else if (n>10) {
    print("n is greater than 10")
  } else {
   print("n is equal to 10")
  }
}
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is less than 10"
[1] "n is equal to 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
[1] "n is greater than 10"
while (g <=10) {
  print(paste(g, "is less than or equal to 10"))
  g <- g+1
}
[1] "0 is less than or equal to 10"
[1] "1 is less than or equal to 10"
[1] "2 is less than or equal to 10"
[1] "3 is less than or equal to 10"
[1] "4 is less than or equal to 10"
[1] "5 is less than or equal to 10"
[1] "6 is less than or equal to 10"
[1] "7 is less than or equal to 10"
[1] "8 is less than or equal to 10"
[1] "9 is less than or equal to 10"
[1] "10 is less than or equal to 10"

Plotting

library(ggplot2)

ggplot(data=africas, mapping = aes(x=year, y=lifeExp)) +
  geom_line() +
  facet_wrap(~country) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(
    x = "Year",
    y = "Life Expectancy",
    title = "Life Expectancy Over Time in African Countries"
  )

ggsave(filename = "./data/AfricanLifeExp.png", plot = AfricanLifeExp, width = 24, height = 40, dpi = 300, units = "cm")
Error in grDevices::dev.off() : 
  QuartzBitmap_Output - unable to open file './data/AfricanLifeExp.png'
pdf(file = "/Users/colinfinlay/GitHub/biol48006220_Fall2022/practcomp_2022/results/AfricanLifeExp.pdf", width = 24, height = 40)
plot(AfricanLifeExp)
dev.off()
null device 
          1 
write.table(gapminder, file="/data/gapminder_web.csv", sep = ",")
Warning: cannot open file '/data/gapminder_web.csv': No such file or directoryError in file(file, ifelse(append, "a", "w")) : 
  cannot open the connection
LS0tCnRpdGxlOiAiQklPTDQ4MDAvNjIyMF9GYWxsMjAyMl9SVHV0b3JpYWwiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKIyBSIEJhc2ljCgojIyBJbnRyb2R1Y3Rpb24KCiMjIyBSIGFzIGEgY2FsY3VsYXRvcgoKYGBge3J9CjEgKyAxMDAKYGBgCgpgYGB7cn0KMl4yCmBgYAoKYGBge3J9CjcvMgpgYGAKCmBgYHtyfQo0LTEKYGBgCgpgYGB7cn0KMioyCmBgYAoKYGBge3J9CjMrNSoyCmBgYAoKYGBge3J9CigzKzUpKjIKYGBgCgpgYGB7cn0KMmUyCmBgYAoKYGBge3J9CjIvMTAwMDAKYGBgCgpgYGB7cn0Kc2luKDEpCmBgYAoKYGBge3J9CmxvZygxKQpgYGAKCmBgYHtyfQpleHAoMCkKYGBgCgpgYGB7cn0KMSA9PSAxCmBgYAoKYGBge3J9CjEgPj0gMQpgYGAKCmBgYHtyfQoxIDwgMQpgYGAKCmBgYHtyfQoxICE9IDIKYGBgCgpgYGB7cn0KeCA8LSAxMAp4CmBgYAoKYGBge3J9CnggKyB4CmBgYAoKYGBge3J9CnggLSA1CmBgYAoKYGBge3J9CnheMgpgYGAKCmBgYHtyfQp5IDwtIHggKyB4CnkKYGBgCgojIyMgVmVjdG9yaXphdGlvbgoKYGBge3J9CjE6NQpgYGAKCmBgYHtyfQoyXigxOjUpCmBgYAoKYGBge3J9CnYgPC0gMTo1CjJedgpgYGAKCmBgYHtyfQpsb2cxMCh2KQpgYGAKCiMjIyBFbnZpcm9ubWVudAoKYGBge3J9CmxzKCkKYGBgCmBgYHtyfQpybSh2KQpscygpCmBgYAoKIyMgUGFja2FnZSBNYW5hZ2VtZW50CgpgYGB7cn0KaW5zdGFsbGVkLnBhY2thZ2VzKCkKYGBgCgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoInZlZ2FuIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkgI0FscmVhZHkgaW5zdGFsbGVkCmBgYAoKYGBge3J9CmxpYnJhcnkodmVnYW4pCmBgYAoKCmBgYHtyfQojcmVtb3ZlLnBhY2thZ2VzKCkKYGBgCgojIyBQcm9qZWN0IE1hbmFnZW1lbnQKCjEuIFNldCB1cCBtYW5hZ2VtZW50IHN0cnVjdHVyZSAoaS5lLiwgImRhdGEiLCAic3JjIiwgInJlc3VsdHMiLCAiZG9jIikKMi4gRGlzY3VzcyBhdm9pZGluZyByZWR1bmRhbmN5IG9mIGZpbGVzCjMuIE1ha2Ugc3VyZSB0byB1c2UgdmVyc2lvbiBjb250cm9sIChpLmUuLCBHaXQpCgojIyBHZXR0aW5nIEhlbHAKCmBgYHtyfQo/cGxvdApgYGAKCmBgYHtyfQpoZWxwKHBsb3QpCmBgYAoKYGBge3J9Cj8iPC0iCmBgYAoKYGBge3J9CnZpZ25ldHRlKCJGQVEtdmVnYW4iKQpgYGAKCmBgYHtyfQpjaXRhdGlvbigidmVnYW4iKQpgYGAKCiMjIERhdGEgYW5kIHRoZWlyIGZvcm1hdHMKCmBgYHtyfQpjYXRzIDwtIGRhdGEuZnJhbWUoY29hdCA9IGMoImNhbGljbyIsICJibGFjayIsICJ0YWJieSIpLAogICAgICAgICAgICAgICAgICAgd2VpZ2h0ID0gYygyLjEsNSwzLjIpLAogICAgICAgICAgICAgICAgICAgbGlrZXNfc3RyaW5nID0gYygxLDAsMSkpCmBgYAoKYGBge3J9CmNhdHMKYGBgCgpgYGB7cn0Kd3JpdGUuY3N2KGNhdHMsIGZpbGUgPSAifi9HaXRIdWIvYmlvbDQ4MDA2MjIwX0ZhbGwyMDIyL3ByYWN0Y29tcF8yMDIyL2RhdGEvY2F0cy5jc3YiKQpgYGAKCmBgYHtyfQpjYXRzJGNvYXQKYGBgCgpgYGB7cn0KY2F0cyR3ZWlnaHQKYGBgCgpgYGB7cn0KY2F0cyR3ZWlnaHQqMTAKYGBgCgpgYGB7cn0KbG9nKGNhdHMkd2VpZ2h0KQpgYGAKCmBgYHtyfQpsb2d3ZWlnaHQgPC0gbG9nKGNhdHMkd2VpZ2h0KQpjYmluZChjYXRzLCBsb2d3ZWlnaHQpCmBgYAoKYGBge3J9CmNhdHMgPC0gY2JpbmQoY2F0cywgbG9nd2VpZ2h0KQpgYGAKCmBgYHtyfQpwYXN0ZSgiTXkgY2F0IGlzICIsIGNhdHMkY29hdCwgIiwgYW5kIGl0IHdlaWdocyAiLCBjYXRzJHdlaWdodCwgIiBrZy4iLCBzZXAgPSAiIikKYGBgCgojIyMgRGF0YSBUeXBlcwoKYGBge3J9CnR5cGVvZihjYXRzJGNvYXQpCmBgYAoKYGBge3J9CnR5cGVvZihjYXRzJHdlaWdodCkKYGBgCgpgYGB7cn0KdHlwZW9mKGNhdHMkbGlrZXNfc3RyaW5nKQpgYGAKCmBgYHtyfQp0eXBlb2YoMy4xNDE1OSkKYGBgCgpgYGB7cn0KdHlwZW9mKDFpKQpgYGAKCmBgYHtyfQp0eXBlb2YoRkFMU0UpCmBgYAoKYGBge3J9CnR5cGVvZihUKQpgYGAKCmBgYHtyfQp0eXBlb2YoY2F0cykKYGBgCgpgYGB7cn0KY2xhc3MoY2F0cykKYGBgCgpgYGB7cn0KZmlsZS5zaG93KCIuL2RhdGEvY2F0cy5jc3YiKQpgYGAKCmBgYHtyfQpjYXRzJGxpa2VzX3N0cmluZyA8LSBhcy5sb2dpY2FsKGNhdHMkbGlrZXNfc3RyaW5nKQp0eXBlb2YoY2F0cyRsaWtlc19zdHJpbmcpCmBgYAoKYGBge3J9CmNhdHMkbGlrZXNfc3RyaW5nCmBgYAoKYGBge3J9CmMoImEiLCAiYiIpCmBgYAoKYGBge3J9CmFiIDwtIGMoImEiLCAiYiIpCmFiCmBgYAoKYGBge3J9CmMoYWIsICJjIikKYGBgCgpgYGB7cn0KYyhhYiwgYWIpCmBgYAoKYGBge3J9CjE6MTAKYGBgCgpgYGB7cn0Kc2VxKDEwKQpgYGAKCmBgYHtyfQp6IDwtIHNlcSgxMCkKaGVhZCh6LCBuPTMpCmBgYAoKYGBge3J9Cmxlbmd0aCh6KQpgYGAKCmBgYHtyfQpjbGFzcyh6KQpgYGAKCmBgYHtyfQp0eXBlb2YoeikKYGBgCgpgYGB7cn0Kc2VxKDAsMTAwLCBieT01KQpgYGAKCiMjIyBEYXRhIEZyYW1lcwpgYGB7cn0KY2F0cwpgYGAKCmBgYHtyfQpzdHIoY2F0cyRjb2F0KQpgYGAKCmBgYHtyfQpjb2F0cyA8LSBjKCJ0YWJieSIsICJ0b3J0b2lzZXNoZWxsIiwgInRvcnRvaXNlc2hlbGwiLCAiYmxhY2siLCAidGFiYnkiKQpjb2F0cwpgYGAKCmBgYHtyfQpzdHIoY29hdHMpCmBgYAoKYGBge3J9CmZhY3Rvcihjb2F0cykKYGBgCgpgYGB7cn0KY2F0ZWdvcmllcyA8LSBmYWN0b3IoY29hdHMpCmNsYXNzKGNvYXRzKQpjbGFzcyhjYXRlZ29yaWVzKQpgYGAKCmBgYHtyfQpzdHIoY2F0ZWdvcmllcykKYGBgCgojIyMgTGlzdHMKCmBgYHtyfQpsaXN0X2V4YW1wbGUgPC0gbGlzdCh0aXRsZT0iTnVtYmVycyIsIG51bWJlcnMgPSAxOjEwLCBkYXRhPVQpCmBgYAoKYGBge3J9Cmxpc3RfZXhhbXBsZQpgYGAKCmBgYHtyfQphbm90aGVyX2xpc3QgPC0gbGlzdCgxLCAiYSIsIFRSVUUsIDErMWkpCmFub3RoZXJfbGlzdApgYGAKCmBgYHtyfQp0eXBlb2YobGlzdF9leGFtcGxlKQpjbGFzcyhsaXN0X2V4YW1wbGUpCmBgYAoKYGBge3J9CnR5cGVvZihjYXRzKQpjbGFzcyhjYXRzKQpgYGAKCmBgYHtyfQpkYXRhLmZyYW1lKGxpc3RfZXhhbXBsZSkKYGBgCgpgYGB7cn0KY2F0cwpjYXRzWywzXQpjYXRzWzMsXQpgYGAKCmBgYHtyfQpjYXRzWzI6MywgYygxLDMpXQpgYGAKCiMjIyBNYXRyaWNlcwoKYGBge3J9CiMgQnkgZGVmaW5pdGlvbiwgbWF0cmljZXMgYXJlIGFsbCBudW1iZXJzCgptYXRyaXhfZXhhbXBsZSA8LSBtYXRyaXgoMCwgbmNvbCA9IDUsIG5yb3cgPSAzKQpgYGAKCmBgYHtyfQptYXRyaXhfZXhhbXBsZQpgYGAKCmBgYHtyfQpjbGFzcyhtYXRyaXhfZXhhbXBsZSkKYGBgCgpgYGB7cn0KdHlwZW9mKG1hdHJpeF9leGFtcGxlKQpgYGAKCmBgYHtyfQpzdHIobWF0cml4X2V4YW1wbGUpCmBgYAoKYGBge3J9CmRpbShtYXRyaXhfZXhhbXBsZSkKYGBgCgpgYGB7cn0KbmNvbChtYXRyaXhfZXhhbXBsZSkKbnJvdyhtYXRyaXhfZXhhbXBsZSkKYGBgCgpgYGB7cn0KY2xhc3MoZGF0YS5mcmFtZShtYXRyaXhfZXhhbXBsZSkpCmBgYAoKYGBge3J9CmRmX2V4YW1wbGUgPC0gZGF0YS5mcmFtZShtYXRyaXhfZXhhbXBsZSkKZGZfZXhhbXBsZQpgYGAKCiMjIyBTdWJzZXR0aW5nCgpgYGB7cn0KcCA8LSBjKDIuMywgNi45LCA0LjAsIDIzLCAxKQpwCmBgYAoKYGBge3J9Cm5hbWVzKHApIDwtIGMoJ2EnLCAnYicsICdjJywgJ2QnLCAnZScpCnAKYGBgCgpgYGB7cn0KcFsxXQpgYGAKCmBgYHtyfQpwWzI6NF0KYGBgCgpgYGB7cn0KcFtjKDEsNSldCmBgYAoKYGBge3J9CnBbYygxLDEsMSwzLDUsNSldCmBgYAoKYGBge3J9CnBbNl0KYGBgCgpgYGB7cn0KcFstM10KYGBgCgpgYGB7cn0KcFtjKC0xLC01KV0KYGBgCgpgYGB7cn0KcFstKDI6NCldCmBgYAoKYGBge3J9CnBbYygnYScsJ2MnKV0KYGBgCgpgYGB7cn0KcFtjKFQsRixULEYsVCldCmBgYAoKYGBge3J9CnBbbmFtZXMocCkgIT0gJ2MnXQpgYGAKCiMjIyBGYWN0b3JzCgpgYGB7cn0KZiA8LSBmYWN0b3IoYygnYScsJ2InLCdjJywnZCcsJ2UnKSkKZgpgYGAKCmBgYHtyfQpmW2Y9PSdhJ10KYGBgCgpgYGB7cn0KZlsxOjNdCmBgYAoKYGBge3J9CmZbZiAlaW4lIGMoJ2InLCdjJyldCmBgYAoKYGBge3J9CmZbLTNdCmBgYAoKYGBge3J9CmYyIDwtIGZhY3RvcihjKCdhJywnYScsJ2QnLCdjJywnYycpKQpmMgpgYGAKCmBgYHtyfQpmMltmMiA9PSAnYSddCmBgYAoKYGBge3J9CmYyW2YyICVpbiUgYygnYScsJ2MnKV0KYGBgCgojIyMgTWF0cmljZXMgUmVzdW1lZAoKYGBge3J9CnNldC5zZWVkKDY1KQptIDwtIG1hdHJpeChybm9ybSg2KjQpLCBuY29sID0gNCwgbnJvdyA9IDYpCm0KYGBgCgpgYGB7cn0KbVssYygzLDQpXQpgYGAKCiMjIyBMaXN0cyBSZXZpc3RlZAoKYGBge3J9CnhsaXN0IDwtIGxpc3QoYT0iQklPTDQ4MDA2MjIwIiwgYj1zZXEoMSwxMCwgYnkgPSAwLjUpLCBkYXRhID0gIkdyYWRlIikKeGxpc3QKYGBgCgpgYGB7cn0KeGxpc3RbMToyXQpgYGAKCmBgYHtyfQp4bGlzdFsnYSddCmBgYAoKYGBge3J9CnhsaXN0W1snYSddXQpgYGAKCmBgYHtyfQp4bGlzdFsnYiddCgp4bGlzdFtbJ2InXV0KYGBgCgpgYGB7cn0KeGxpc3QkYgpgYGAKCiMjIyBEYXRhIEZyYW1lcyBSZXZpc3RlZAoKYGBge3J9CmdldHdkKCkKZ3AgPC0gcmVhZC5jc3YoIi9Vc2Vycy9jb2xpbmZpbmxheS9HaXRIdWIvYmlvbDQ4MDA2MjIwX0ZhbGwyMDIyL3ByYWN0Y29tcF8yMDIyL2RhdGEvZm9yZXN0X2FyZWFfc3Ffa20uY3N2IikKYGBgCgpgYGB7cn0KaGVhZChncCwgbj0xMEwpCmBgYAoKYGBge3J9CmhlYWQoZ3BbM10sIG49MTBMKQpgYGAKCmBgYHtyfQpucm93KGdwKQpgYGAKCmBgYHtyfQpoZWFkKGdwW1siY291bnRyeSJdXSwgMTBMKQpgYGAKCmBgYHtyfQpncCRYMjAwMQpgYGAKCmBgYHtyfQpncFsxOjMsIDI6NV0KYGBgCgpgYGB7cn0KZ3BbIHdoaWNoKGdwJFgxOTg5IDw9IDEwMCAmIGdwJFgyMDE5ID49IDEwMCksXQpgYGAKCiMjIyBDb25kaXRpb25hbHMgYW5kIEZsb3cKCmBgYHtyfQpuIDwtIDEwCgppZiAobjwxMCkgewogIHByaW50KCJuIGlzIGxlc3MgdGhhbiAxMCIpCn0gZWxzZSBpZiAobj4xMCkgewogIHByaW50KCJuIGlzIGdyZWF0ZXIgdGhhbiAxMCIpCn0gZWxzZSB7CiAgcHJpbnQoIm4gaXMgZXF1YWwgdG8gMTAiKQp9CmBgYAoKYGBge3J9CmZvciAobiBpbiBzZXEoMSwyMCkpIHsKICBpZiAobjwxMCkgewogICAgcHJpbnQoIm4gaXMgbGVzcyB0aGFuIDEwIikKICB9IGVsc2UgaWYgKG4+MTApIHsKICAgIHByaW50KCJuIGlzIGdyZWF0ZXIgdGhhbiAxMCIpCiAgfSBlbHNlIHsKICAgcHJpbnQoIm4gaXMgZXF1YWwgdG8gMTAiKQogIH0KfQpgYGAKCmBgYHtyfQpnIDwtIDAKCndoaWxlIChnIDw9MTApIHsKICBwcmludChwYXN0ZShnLCAiaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIDEwIikpCiAgZyA8LSBnKzEKfQpgYGAKCiMjIyBQbG90dGluZwoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKYGBgCgpgYGB7cn0KZ3AgPC0gcmVhZC5jc3YoIi9Vc2Vycy9jb2xpbmZpbmxheS9HaXRIdWIvYmlvbDQ4MDA2MjIwX0ZhbGwyMDIyL3ByYWN0Y29tcF8yMDIyL2RhdGEvZ2FwbWluZGVyX2FsbC5jc3YiKQoKaGVhZChncCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBncCwgbWFwcGluZyA9IGFlcyh4PWdkcFBlcmNhcF8xOTUyLCB5PXBvcF8xOTUyKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBncCwgbWFwcGluZyA9IGFlcyh4PWdkcFBlcmNhcF8yMDAyLCB5PXBvcF8yMDAyKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2FwbWluZGVyIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3djYXJwZW50cnkvci1ub3ZpY2UtZ2FwbWluZGVyL2doLXBhZ2VzL19lcGlzb2Rlc19ybWQvZGF0YS9nYXBtaW5kZXJfZGF0YS5jc3YiKQoKaGVhZChnYXBtaW5kZXIpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gZ2FwbWluZGVyLCBtYXBwaW5nID0gYWVzKHg9Z2RwUGVyY2FwLCB5PWxpZmVFeHApKSArIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1nYXBtaW5kZXIsIG1hcHBpbmcgPSBhZXMoeD15ZWFyLCB5PWxpZmVFeHAsIGJ5PWNvdW50cnksIGNvbG9yPWNvbnRpbmVudCkpICsgZ2VvbV9saW5lKCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z2FwbWluZGVyLCBtYXBwaW5nID0gYWVzKHg9eWVhciwgeT1saWZlRXhwLCBieT1jb3VudHJ5KSkgKyBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyhjb2xvcj1jb250aW5lbnQpKSArIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGdhcG1pbmRlciwgbWFwcGluZyA9IGFlcyh4PWdkcFBlcmNhcCwgeT1saWZlRXhwKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgc2NhbGVfeF9sb2cxMCgpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhPWdhcG1pbmRlciwgbWFwcGluZz1hZXMoeD1nZHBQZXJjYXAsIHk9bGlmZUV4cCkpICsKICBnZW9tX3BvaW50KGFscGhhPTAuMjUsIGNvbG9yPSJwdXJwbGUiKSsKICBzY2FsZV94X2xvZzEwKCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBjb2xvcj0iZ29sZCIpCmBgYAoKYGBge3J9CmFmcmljYXMgPC0gZ2FwbWluZGVyW2dhcG1pbmRlciRjb250aW5lbnQ9PSJBZnJpY2EiLCBdCmBgYAoKYGBge3J9CkFmcmljYW5MaWZlRXhwIDwtIGdncGxvdChkYXRhPWFmcmljYXMsIG1hcHBpbmcgPSBhZXMoeD15ZWFyLCB5PWxpZmVFeHApKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmNvdW50cnkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKwogIGxhYnMoCiAgICB4ID0gIlllYXIiLAogICAgeSA9ICJMaWZlIEV4cGVjdGFuY3kiLAogICAgdGl0bGUgPSAiTGlmZSBFeHBlY3RhbmN5IE92ZXIgVGltZSBpbiBBZnJpY2FuIENvdW50cmllcyIKICApCmBgYAoKYGBge3J9Cmdnc2F2ZShmaWxlbmFtZSA9ICIvVXNlcnMvY29saW5maW5sYXkvR2l0SHViL2Jpb2w0ODAwNjIyMF9GYWxsMjAyMi9wcmFjdGNvbXBfMjAyMi9kYXRhL0FmcmljYW5MaWZlRXhwLnBuZyIsIHBsb3QgPSBBZnJpY2FuTGlmZUV4cCwgd2lkdGggPSAyNCwgaGVpZ2h0ID0gNDAsIGRwaSA9IDMwMCwgdW5pdHMgPSAiY20iKQpgYGAKCmBgYHtyfQpwZGYoZmlsZSA9ICIvVXNlcnMvY29saW5maW5sYXkvR2l0SHViL2Jpb2w0ODAwNjIyMF9GYWxsMjAyMi9wcmFjdGNvbXBfMjAyMi9yZXN1bHRzL0FmcmljYW5MaWZlRXhwLnBkZiIsIHdpZHRoID0gMjQsIGhlaWdodCA9IDQwKQpwbG90KEFmcmljYW5MaWZlRXhwKQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0Kd3JpdGUudGFibGUoZ2FwbWluZGVyLCBmaWxlPSIvVXNlcnMvY29saW5maW5sYXkvR2l0SHViL2Jpb2w0ODAwNjIyMF9GYWxsMjAyMi9wcmFjdGNvbXBfMjAyMi9kYXRhL2dhcG1pbmRlcl93ZWIuY3N2Iiwgc2VwID0gIiwiKQpgYGAKCmBgYHtyfQp3cml0ZS5jc3YoYWZyaWNhcywgZmlsZT0iL1VzZXJzL2NvbGluZmlubGF5L0dpdEh1Yi9iaW9sNDgwMDYyMjBfRmFsbDIwMjIvcHJhY3Rjb21wXzIwMjIvZGF0YS9nYXBtaW5kZXJfd2ViX2FmcmljYXMuY3N2IikKYGBgCgoKCg==